package com.ice.work.moment.crawler.task;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.honeybee.cloud.framework.common.constant.CommonSystemConstant;
import com.honeybee.cloud.framework.common.enums.ResponseEnum;
import com.honeybee.cloud.framework.common.page.Page;
import com.honeybee.cloud.framework.mybatis.page.PageMapper;
import com.ice.work.moment.crawler.service.IShareService;
import com.ice.work.moment.crawler.service.IlPositionTypeService;
import com.ice.work.moment.facade.crawler.dto.PositionTypeDTO;
import com.ice.work.moment.facade.crawler.dto.ShareDTO;
import com.ice.work.moment.facade.crawler.model.PositionType;
import com.ice.work.moment.facade.crawler.model.Share;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.Future;

/**
 * @Description 爬虫异步实现
 * @Author DELL
 * @Create 2019-05-10
 * @Since 1.0.0
 */
@Component
@EnableAsync
public class CrawlerAsyncTask {
    @Autowired
    private IShareService shareService;
    @Autowired
    private IlPositionTypeService positionTypeService;

    @Async
    public Future<String> getAllAShareTask(PageProcessor processor, Integer size) {
        List<String> urls = Lists.newArrayList();
        for (int i = 1; i <= size; i++) {
            String url = getAllShareUrl(i);
            urls.add(url);
        }
        String[] urlArray = new String[urls.size()];
        runSpider(processor, urls.toArray(urlArray));
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }

    @Async
    public Future<String> getAllShareTradingTask(PageProcessor processor) {
        List<String> urls = Lists.newArrayList();
        Long currPage = 1L;
        Long size = 200L;
        Long totalPage;
        do {
            IPage<Share> iPage = PageMapper.INSTANCE.pageInfo(currPage, size);
            Page<ShareDTO> page = shareService.page(iPage);
            List<ShareDTO> shareDTOList = page.getRecords();
            for (ShareDTO shareDTO : shareDTOList) {
                String url = getShareDetailUrl(shareDTO.getCode());
                urls.add(url);
            }
            totalPage = page.getTotal();
            currPage++;
        } while (currPage < totalPage);
        String[] urlArray = new String[urls.size()];
        runSpider(processor, urls.toArray(urlArray));
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }

    @Async
    public Future<String> getAShareTradingTask(PageProcessor processor, Long id) {
        ShareDTO shareDTO = shareService.findById(id);
        if (Objects.isNull(shareDTO)) {
            return new AsyncResult<>(ResponseEnum.FAIL.value);
        }
        String url = getShareDetailUrl(shareDTO.getCode());
        runSpider(processor, url);
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }

    @Async
    public Future<String> getAllShareCommentTask(PageProcessor processor, Integer size, Long shareId) {
        ShareDTO shareDTO = null;
        if (Objects.nonNull(shareId)) {
            shareDTO = shareService.findById(shareId);

        }
        if (Objects.nonNull(shareId) && Objects.isNull(shareDTO)) {
            return new AsyncResult<>(ResponseEnum.FAIL.value);
        }
        List<String> urls = Lists.newArrayList();
        if (Objects.nonNull(shareDTO)) {
            String url = getAllCommentUrl(1, shareDTO.getCode());
            urls.add(url);
        } else {
            for (int i = 1; i <= size; i++) {
                String url = getAllCommentUrl(i);
                urls.add(url);
            }
        }
        String[] urlArray = new String[urls.size()];
        runSpider(processor, urls.toArray(urlArray));
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }

    /**
     * 爬取机构持仓
     *
     * @param processor
     * @param pageLimits 总页数
     * @return
     */
    @Async
    public Future<String> getPositionTask(PageProcessor processor, long pageLimits) {
        List<String> urls = Lists.newArrayList();
        Long currPage = 1L;
        Long size = 200L;
        Long totalPage;
        do {
            IPage<PositionType> iPage = PageMapper.INSTANCE.pageInfo(currPage, size);
            Page<PositionTypeDTO> page = positionTypeService.page(iPage);
            List<PositionTypeDTO> typeDTOList = page.getRecords();
            for (PositionTypeDTO typeDTO : typeDTOList) {
                if (Objects.isNull(typeDTO.getParentId())) {
                    continue;
                }
                for (long i = 0; i < pageLimits; i++) {
                    String url = getInstitutionalPositionUrl(typeDTO.getValue(), i);
                    urls.add(url);
                }
            }
            totalPage = page.getTotal();
            currPage++;
        } while (currPage < totalPage);
        String[] urlArray = new String[urls.size()];
        runSpider(processor, urls.toArray(urlArray));
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }


    @Async
    public Future<String> getPositionTypeTask(PageProcessor processor) {
        runSpider(processor, getInstitutionalPositionTypeUrl());
        return new AsyncResult<>(ResponseEnum.SUCCESS.value);
    }

    /**
     * 详情url
     *
     * @param code
     * @return
     */
    private String getShareDetailUrl(String code) {
        String url = "http://quote.cfi.cn/quote_" + code + ".html";
        return url;
    }

    /**
     * 列表url
     *
     * @param page
     * @return
     */
    private String getAllShareUrl(Integer page) {
        String url = "http://data.cfi.cn/quotelist.aspx?sortcol=stockname&sortfd=%E4%BB%A3%E7%A0%81&marketid=&hy=&sectypeid=1&sortway=asc&scb=&marketkey=&stockcode=&mystock=&page=" + page;
        return url;
    }

    /**
     * 评论URL
     *
     * @param page
     * @return
     */
    private String getAllCommentUrl(Integer page, String shareCode) {
        String url = "http://data.cfi.cn/cfidata.aspx?sortfd=&sortway=&ndk=A0A1934A1939A3230A3231&fr=content&xztj=&mystock=&curpage=" + page + "&searchstock=" + StrUtil.emptyToDefault(shareCode, "");
        return url;
    }

    /**
     * 评论URL
     *
     * @param page
     * @return
     */
    private String getAllCommentUrl(Integer page) {
        return getAllCommentUrl(page, null);
    }

    /**
     * 机构持仓类型url
     *
     * @return
     */
    private String getInstitutionalPositionTypeUrl() {
        String url = "http://data.cfi.cn/cfidata.aspx?fr=menu";
        return url;
    }

    /**
     * 机构持仓url
     *
     * @return
     */
    private String getInstitutionalPositionUrl(String value, Long page) {
        String url = "http://data.cfi.cn/cfidata.aspx?sortfd=&sortway=&curpage=" + page + "&ndk=" + value + "&xztj=&mystock=&fr=content";
        return url;
    }

    /**
     * 启动爬虫
     *
     * @param urls
     */
    private void runSpider(PageProcessor pageProcessor, String... urls) {
        Spider.create(pageProcessor).addUrl(urls).thread(CommonSystemConstant.CRAWLER_THREAD_SIZE).run();
    }
}
